﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using jade.core;
using TravelLib;
using jade.core.behaviours;
using jade.lang.acl;

namespace MultiAgentLib
{
    public class CompanyAgent : Agent
    {
        private Company _company;
        public AgentForm Form
        {
            get;
            private set;
        }
        public Company Company
        {
            get { return _company; }
        }
        private ConsoleColor _color;

        public override void setup()
        {
            
            object[] args = this.getArguments();
            _color = Color.GetColor();
            if (args != null)
            {
                _company = args[0] as Company;
                Form = args[1] as AgentForm;
                Form.Show();
                Form.AddTextLine(_company.CompanyName + " waiting for requests ");
            }
            else
            {
                _company = null;
            }
            if (_company != null)
            {
                //add behaviors
            }
            RegisterService();
            addBehaviour(new WinFormRefreshBehaviour2(this, 100));
            addBehaviour(new RespondBehaviour(this));
        }

        private void RegisterService()
        {
            try
            {
                YellowPages.RegisterService("Services.Company", this);
                WriteConsole("Services.Company service registered");
            }
            catch (Exception exc)
            {
                WriteConsole("Exception registering service: " + exc.Message);
            }
        }

        public void WriteConsole(string s)
        {
            Console.BackgroundColor = _color;
            Console.ForegroundColor = ConsoleColor.Black;
            Console.WriteLine("[" + getLocalName() + "]: " + s);
            if(Form!=null)
                Form.AddTextLine(s);
        }
    }

    internal class RespondBehaviour : CyclicBehaviour
    {
        private new CompanyAgent myAgent;

        public RespondBehaviour(CompanyAgent a) : base(a) { myAgent = a; }

        public override void action()
        {
            MessageTemplate pattern1 = MessageTemplate.MatchConversationId("ASK");
            ACLMessage message1 = myAgent.receive(pattern1);
            if (message1 != null)
            {
                myAgent.WriteConsole(myAgent.Company.CompanyName + " tries to answer to " + message1.getSender().getLocalName());

                RouteWrapper route = Utils.DeSerializeObject<RouteWrapper>(message1.getContent());

                List<FlightWrapper> foundFlights = myAgent.Company.GetCorrespondingFlights(route);

                //Send response
                ACLMessage response = new ACLMessage(ACLMessage.AGREE);
                response.addReceiver(message1.getSender());
                response.setConversationId("OFFER");
                myAgent.WriteConsole(myAgent.Company.CompanyName + " sending "+foundFlights.Count + " offers ");
                response.setContent(Utils.SerializeObject<List<FlightWrapper>>(foundFlights));
                myAgent.send(response);
            }
            else
            {
                //myAgent.WriteConsole(myAgent.Company.CompanyName + " received invalid message ");
            }
        }
    }

    internal class WinFormRefreshBehaviour2 : TickerBehaviour
    {
        private new CompanyAgent myAgent;
        public WinFormRefreshBehaviour2(CompanyAgent a, long period) : base(a, period) { myAgent = a; }
        public override void onTick()
        {
            myAgent.Form.DoEvents();
        }
    }
}
